package org.eclipse.epsilon.emc.rdbms.core.sqlstatement;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.emc.epsilon.rdbms.core.typemapper.TypeMapper;


public abstract class SQLStatement 
{
	String databaseName;
	String schemaName;
	String tableName;

	public abstract String BuildForCriteria(ResultSet sqlTables, HashMap properties,HashMap<String, Object> props) throws SQLException; //For Update
	public abstract String BuildForCriteria(ResultSet sqlTables,HashMap<String, Object> props) throws SQLException;  //ForDelete
	public abstract String BuildForCriteria(ResultSet tableInfo,ArrayList<String> properties, HashMap<String, Object> criteria) throws SQLException;  //For Select
	public abstract String BuildForCriteria(ResultSet tableInfo, ResultSet sqlColumns,ResultSet primaryKey, ResultSet columnMetaData,HashMap <String, Object> properties) throws SQLException;  //For insert
    public abstract String BuildForCriteria(ResultSet sqlTables, ArrayList<String> columns, ArrayList PKtables,ArrayList FKtables,ArrayList PKcols,ArrayList FKcols,  HashMap <String, Object> parameters) throws SQLException;
	
	
    /** This method returns the string value for the object
     * @param statement
     * @return The string of the statement object
	*/		
	public String asString(Object statement)	
	{
		return statement.toString();
	}
	
	/** This method is used to get an arraylist from a resultset.
	 * @param resultset This is the resultset of that you want to get the list from
	 * @param columnName This is the specific name of the column to retrieve in the resultset
	 * @return newArray returns the new array of the columns
	*/	
	protected ArrayList<String> getArrayListFromResultSet(ResultSet ResultSet,String columnName) throws SQLException 
	{
		ArrayList<String> newArray = new ArrayList<String>();
		while (ResultSet.next()) 
   	   {
         newArray.add(ResultSet.getString(columnName).toString());
       }
		return newArray;	
	}
	
	/** This method is used to get a string from an array list
	 * @param columnNames This is a list of columns that we want to get the string for
	 * @param removecolumns This is a list of columns that we do not want in our string.
	 * @return statement Returns part of the SQL Statement to be generated.
	*/	
	protected String getStringFromArrayList(ArrayList<String> columnNames, ArrayList<String> removeColumns) 
	{
	String statement = "";
	if(columnNames==null)
	{
		statement = " * ";	
	}
	else
	{	
	for(int i=0;i<columnNames.size();i++)
	{ 
       if((removeColumns.contains(columnNames.get(i))))
        {
    	   //dont do anything as we want to ignore this column from the Insert Statement
        }
       else 
       {
		statement = statement + (columnNames.get(i));
		if(i < columnNames.size()-1)
		{
		statement = statement+",";	
		}
       }
	}
	}
	return statement;	
	}

	/** This method is used to get a the values from an array list
	 * @param columnNames This is a list of columns that we want to get the string for
	 * @param removecolumns This is a list of columns that we do not want in our string.
	 * @param tableName This is the name of the table in the SQLStatement
	 * @param properties 
	 * @return statement Returns part of the SQL Statement to be generated.
	*/	
	protected String getValues(ResultSet ColumnNames, ArrayList<?> removeColumns, String tableName, HashMap properties) throws SQLException 
	{	
		if(properties==null)
		{
			properties = new HashMap();
		}
		String statement = "";		
		TypeMapper tm = new TypeMapper();
		int i=0;
		while (ColumnNames.next()) 
		{	
			i++;
			if(ColumnNames.getMetaData().isAutoIncrement(i)==true) //This seems to always return false....and therefore inserts fail.
			{

				//We dont want to do anything here as its an auto incremental column
			}
			else if(removeColumns.contains(ColumnNames.getString(4).toString()))
			{

				//We do not want to do anything with Primary Key Columns.
			}
			//We first check if the column can have null values and is writable. 
			else if(ColumnNames.getBoolean(11)==true && ColumnNames.getMetaData().isWritable(i)==true) 
			{
				//So know that the column is nullable but lets check to see if we need to insert null value or another default value specified.
				if(properties != null && properties.containsKey(ColumnNames.getString(4))==true)
				{
					statement = statement + "'" +properties.get(ColumnNames.getString(4))+"'";
					//statement = statement + "'" +properties.containsValue(rs.getString(4))+"'";           	  
					//We need to override the default for the insert statement.
				}
				else
				{
					statement = statement + "null";
				}
				if(ColumnNames.isLast()==false)
				{
					statement = statement+","; 
				}
			}
			//Now we must check that if the column is not nullable what data type the column is so we can insert a valid placeholder for the data.
			else if(ColumnNames.getBoolean(11)==false) 				
			{	 
				if(properties.containsKey(ColumnNames.getString(4))==true)
				{
					statement = statement +"'"+properties.containsValue(ColumnNames.getString(4))+"'";           	  
					//We need to override the default for the insert statement.
				}
				else
				{
					statement= statement + "'"+ tm.getMappedDataTypeDefault(ColumnNames.getString(6).toString()) + "'";
				}
				if(ColumnNames.isLast()==false)
				{
					statement = statement+","; 
				}				
			} 
		}
		return statement;
	}

	
	/** This method is used to generate the SQL statement string from the hashmap values
	 * @param hashmap The hashmap to obtain the string from
	 * @param removecolumns The string seperator between the hashmap values.
	 * @return statement Returns part of the SQL Statement to be generated.
	*/	
	protected String getStringFromHashMap(HashMap<String, Object> hashMap,String seperator) 
	{		
		 String statement = "";
		 java.util.Iterator<Entry<String, Object>> it = hashMap.entrySet().iterator(); 
		 while (it.hasNext()) 
		 { 
		      Map.Entry pairs = (Map.Entry) it.next(); 
		      if(pairs.getValue()==null)
		      {
		    	  statement = statement +  pairs.getKey() + " is " + pairs.getValue()+"";
		      }
		      else
		      { 	  
		      statement = statement +  pairs.getKey() + " = '" + pairs.getValue()+"'";
		      }
		      if(it.hasNext()==true)
		      {	    	
		    	  statement = statement + " "+seperator+" "; 
		      }
	     }
		return statement;
	}
	
	protected String getKeyFromHashMap(HashMap<String, Object> hashMap) 
	{		
		 String statement = "";
		 java.util.Iterator<Entry<String, Object>> it = hashMap.entrySet().iterator(); 
		 while (it.hasNext()) 
		 { 
		      Map.Entry pairs = (Map.Entry) it.next(); 
		      statement = statement +  pairs.getKey();
	     }
		return statement;
	}
	
		
	
	
}
